package com.devilwwj.http.core;

import com.devilwwj.http.exception.HttpException;

import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;


import java.io.IOException;
import java.util.Map;

/**
 * @desc HttpClient请求工具类
 */
public class HttpClientUtil {
    private static HttpClient client;
    private static final int TIMEOUT = 1000;
    private static final int CONNECT_TIMEOUT = 2000;
    private static final int SO_TIMEOUT = 4000;
    private static final String SCHEME_HTTP = "http";
    private static final String SCHEME_HTTPS = "https";

    /**
     * 通用HttpClient请求方法
     *
     * @param request
     * @return
     */
    public static HttpResponse execute(Request request) throws HttpException {
        switch (request.method) {
            case GET:
            case DELETE:
                return get(request);
            case POST:
            case PUT:
                return post(request);
            default:
                throw new HttpException(HttpException.ErrorType.MANUAL, "the request method " + request.method.name() + " can't be supported");
        }
    }

    /**
     * GET请求
     *
     * @param request
     * @return HttpResponse
     * @throws HttpException 自定义异常
     */
    private static HttpResponse get(Request request) throws HttpException {
        try {
            HttpClient client = getHttpClient();
            HttpGet get = new HttpGet(request.url);
            addHeader(get, request.headers);

            return client.execute(get);
        } catch (ConnectTimeoutException e) {
            throw new HttpException(HttpException.ErrorType.TIMEOUT, e.getMessage());
        } catch (ClientProtocolException e) {
            throw new HttpException(HttpException.ErrorType.SERVER, e.getMessage());
        } catch (IOException e) {
            throw new HttpException(HttpException.ErrorType.SERVER, e.getMessage());
        }
    }

    /**
     * POST请求
     *
     * @param request
     * @return
     * @throws HttpException
     */
    private static HttpResponse post(Request request) throws HttpException {
        try {
            HttpClient client = getHttpClient();
            HttpPost post = new HttpPost();
            // 如果请求实体为空，则抛出异常
            if (request.content == null) {
                throw new HttpException(HttpException.ErrorType.MANUAL, "you should set post content when use POST to request");
            }
            addHeader(post, request.headers);
            StringEntity entity = new StringEntity(request.content);
            post.setEntity(entity);

            return client.execute(post);
        } catch (ConnectTimeoutException e) {
            throw new HttpException(HttpException.ErrorType.TIMEOUT, e.getMessage());
        } catch (ClientProtocolException e) {
            throw new HttpException(HttpException.ErrorType.SERVER, e.getMessage());
        } catch (IOException e) {
            throw new HttpException(HttpException.ErrorType.SERVER, e.getMessage());
        }
    }

    /**
     * 获取HttpClient实例化对象
     *
     * @return
     */
    public static synchronized HttpClient getHttpClient() {
        if (null == client) {
            HttpParams params = new BasicHttpParams();
            // 设置一些基本参数
            HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
            HttpProtocolParams.setContentCharset(params, "UTF-8");
            HttpProtocolParams.setUseExpectContinue(params, true);
            HttpProtocolParams.setUserAgent(params, "Mozilla/5.0(Linux;U;Android 2.2.1;en-us;Nexus One Build.FRG83) "
                    + "AppleWebKit/553.1(KHTML,like Gecko) Version/4.0 Mobile Safari/533.1");


            // 超时设置
            /* 从连接池中取连接的超时时间 */
            ConnManagerParams.setTimeout(params, TIMEOUT);
            /* 连接超时 */
            HttpConnectionParams.setConnectionTimeout(params, CONNECT_TIMEOUT);
            /* 请求超时 */
            HttpConnectionParams.setSoTimeout(params, SO_TIMEOUT);
            /* 设置我们的HttpClient支持HTTP和HTTPS两种模式*/
            SchemeRegistry schReg = new SchemeRegistry();
            schReg.register(new Scheme(SCHEME_HTTP, PlainSocketFactory.getSocketFactory(), 80));
            schReg.register(new Scheme(SCHEME_HTTPS, SSLSocketFactory.getSocketFactory(), 443));
            /* 使用线程安全的连接管理来创建HttpClient */
            ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params, schReg);
            client = new DefaultHttpClient(conMgr, params);
        }
        return client;
    }


    /**
     * 添加Header信息
     *
     * @param mUriRequest
     * @param headers
     */
    private static void addHeader(HttpUriRequest mUriRequest, Map<String, String> headers) {
        if (headers != null && headers.size() > 0) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                mUriRequest.addHeader(entry.getKey(), entry.getValue());
            }
        }
    }


}
